#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <errno.h>

#include <sys/ioctl.h>
#include "../inc/at91_ioctl.h"
#include "../inc/at91_gpio.h"
#include "../inc/serial.h"

static int speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1800, B1200, B600, B300};
static int name_arr[]  = {230400,  115200,  57600,  38400,  19200,  9600,  4800,  2400,  1800,  1200,  600,  300};

/*int set_gpio()
{
	at91_pio_arg arg;
	int fd_pio;

	fd_pio = open(DEV_PIO,O_RDWR);
	if(fd_pio < 0)
	{
		printf("open pio failed \n");
		return -1;
	}

	arg.pin_idx = AT91_PIN_PE24;
	arg.pin_dir = AT91PIO_DIR_OUT;
	arg.pin_sta = 1;
	
	ioctl(fd_pio,IOCTL_PIO_SETDIR,&arg);

	ioctl(fd_pio, IOCTL_PIO_GETSTA, &arg);
	printf("PIN %d, VAL = %d\n", AT91_PIN_PA4, arg.pin_sta);

	close(fd_pio);

	return 0;
}*/

int set_speed(int fd, int speed)
{
    int   i; 
    int   status; 
    struct termios   Opt;
    
    tcgetattr(fd, &Opt); 

    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++) 
	{ 
        if (speed == name_arr[i])
//    	if (speed == speed_arr[i])
        {     
            tcflush(fd, TCIOFLUSH);     
            cfsetispeed(&Opt, speed_arr[i]);  
            cfsetospeed(&Opt, speed_arr[i]);   
            status = tcsetattr(fd, TCSANOW, &Opt);  
            if  (status != 0) 
            {        
                perror("tcsetattr fd");  
                return -1;     
            }    
            tcflush(fd,TCIOFLUSH);   
			return 0;
        }  
    }
    return -1;
}


int set_other_attribute(int fd, int databits, int stopbits, int parity, int mode, char timeOut)
{ 
    struct termios options; 

    if (tcgetattr(fd, &options) != 0) 
    { 
        perror("SetupSerial 1");     
        return -1;  
    }
    options.c_cflag &= ~CSIZE; 
    switch (databits) /*ÉÖÊ¾Ý»Ê*/
    {   
        case 7:		
            options.c_cflag |= CS7; 
            break;
        case 8:     
            options.c_cflag |= CS8;
            break;   
        default:    
            fprintf(stderr,"Unsupported data size\n"); 
            return -1;  
    }
    switch (parity) 
    {   
        case 'n':
        case 'N':    
            options.c_cflag &= ~PARENB;   /* Clear parity enable */
            options.c_iflag &= ~INPCK;     /* Enable parity checking */ 
            break;  
        case 'o':   
        case 'O':    
		case 1:
            options.c_cflag |= (PARODD | PARENB); /* ÉÖΪÆЧÑ*/  
            options.c_iflag |= INPCK;             /* Disnable parity checking */ 
            break;  
        case 'e':  
        case 'E':   
		case 2:
            options.c_cflag |= PARENB;     /* Enable parity */    
            options.c_cflag &= ~PARODD;    /* ת»»ΪżЧÑ*/     
            options.c_iflag |= INPCK;      /* Disnable parity checking */
            break;
        case 'S': 
        case 's':  /*as no parity*/   
		case 0:
            options.c_cflag &= ~PARENB;
            options.c_cflag &= ~CSTOPB;
            break;  
        default:   
            fprintf(stderr,"Unsupported parity\n");    
            return -1;  
    }  
    /* ÉÖֹͣλ*/  
    switch (stopbits)
    {   
        case 1:    
            options.c_cflag &= ~CSTOPB;  
            break;  
        case 2:    
            options.c_cflag |= CSTOPB;  
            break;
        default:    
            fprintf(stderr,"Unsupported stop bits\n");  
            return -1; 
    } 
    /* Set input parity option */ 
    if (parity != 'n')   
        options.c_iflag |= INPCK; 
    tcflush(fd,TCIFLUSH);
    options.c_iflag = 0;
    options.c_oflag = 0;
    options.c_lflag = 0;  
    options.c_cc[VTIME] = timeOut; /*timeOut * 0.1s*/   
    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
//	options.c_oflag 0;

	switch(mode)
	{
		case 1://rs485
			options.c_cflag |= RS485;
			printf("Enable RS485 !\n");
			break;
		case 2://HWHD
			options.c_cflag |= HWHD;
			printf("Enable HWHD !\n");
			break;
		case 3://Modem
			options.c_cflag |= Modem;
			printf("Enable Modem !\n");
			break;
		case 4://ISO7816T0
			options.c_cflag |= ISO7816T0;
			printf("Enable ISO7816 T=0 \n");
			break;
		case 5://ISO7816T1
			options.c_cflag |= ISO7816T1;
			printf("Enable ISO7816 T=1 \n");
			break;
		case 6://IrDA
			options.c_cflag |= IrDA;
			printf("Enable IrDA \n");
			break;
		default:
//			printf("are you kidden me! \n");
			break;
	
	}


if (tcsetattr(fd,TCSANOW,&options) != 0)   
    { 
        perror("SetupSerial 3");   
        return -1;  
    }
 
#if 0	
    tcgetattr(fd, &options);
    printf("c_iflag: %x\rc_oflag: %x\n", options.c_iflag, options.c_oflag);
    printf("c_cflag: %x\nc_lflag: %x\n", options.c_cflag, options.c_lflag);
    printf("c_line: %x\nc_cc[VTIME]: %d\nc_cc[VMIN]: %d\n", options.c_line, options.c_cc[VTIME], options.c_cc[VMIN]);
#endif
    return 0;  
}

/*int main(int argc, char *argv[])
{
	int fd0, fd1,fd2,fd3;
	char temp[1024];
	char string[] = "this is serial test string!!\n";
	int i = 0;
	int d = 0;
	struct termios options;	

	printf("serial test ...\n");
		
	//set_gpio();

	fd0 = open(SERIAL0, O_RDWR,1);	
	fd1 = open(SERIAL1, O_RDWR,1) ;
    fd2 = open(SERIAL2, O_RDWR,1) ;
    fd3 = open(SERIAL3, O_RDWR,1) ;

	if (fd0 < 0) {
		printf("open serial 0 error! %d\n", fd0);
	}
	if (fd1 < 0) {
		printf("open serial 1 error! %d\n", fd1);
	}
    if (fd2 < 0) {
        printf("open serial 2 error! %d\n", fd2);
    }

	printf("set speed ...\n");
	set_speed(fd0, 115200);
	set_speed(fd1, 115200);
    set_speed(fd2, 115200);
    set_speed(fd3, 115200);
	printf("set attribute ...\n");
	
	set_other_attribute(fd0, 8, 1, 0,0);
	set_other_attribute(fd1, 8, 1, 0,1);
    set_other_attribute(fd2, 8, 1, 0,1);
	
//	if (argc < 2)
//		fd = fd0;
//	else {
//	switch (argv[1][0]){
//		case '2': 
//			fd = fd1;
//			break;
//		case '3':
//			fd = fd2;
//			break;
//		default:
//			fd = fd0;
//	}}	

#if 0
 
        //read test
        for (;;) {
                i = read(fd, temp, 1024);
                if (i) {
                        printf("get data: %d\r\n", i);
                        write(fd, temp, i);
                }
        }
       
#else  
        //Write test
        for (;;){
                for (i=0; i<64; i++)
                        temp[i] = i+'0';
                temp[61] = '\r';
                temp[62] = '\n';
                temp[63] = '\0';
                i = write(fd0, temp, 64);
                i = write(fd1, temp, 64);
                i = write(fd2, temp, 64);
                i = write(fd3, temp, 64);
                printf("%d bytes data had sent...\n", i);
                sleep(1);
        }

#endif
	close(fd0);
	close(fd1);
	close(fd2);
	return 0;
}*/

